8: Revoking Credentials
Revoking a credential can take one of two routes depending on the issuer's use case.
Depending on the frequency and volume of credential revocations, issuers may choose to batch publish their revocations or not. Since there is a cost associated with publishing revocations to the ledger, it is recommended that issuers batch revocations when possible.
Automatic Publishing of Revocations
[!WARNING] This endpoint should not be used to revoke more than one credential in quick succession. For multiple revocations, follow the batching route.
The fast and easy way to revoke a credential is to automatically publish the revocation to the ledger, as shown in the example below.
POST /v1/issuer/credentials/revoke
{
"credential_exchange_id": "v2-af4bad3f-3fcc-47ab-85e6-24224dcb2779",
"credential_definition_id": "QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic",
"auto_publish_on_ledger": true
}
The endpoint will respond with:
{
"cred_rev_ids_published": {
"QrMaE11MnC6zjKNY1pxbq8:4:QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic:CL_ACCUM:53462552-d716-4b0b-8b5c-914a3574d2c4": [2]
}
}
The "issuer_cred_rev"
event will fire again with the updated status revoked.
{
"wallet_id": "5df42bab-6719-4c8a-a615-8086435d4de4",
"topic": "issuer_cred_rev",
"origin": "tenant faber",
"group_id": "GroupA",
"payload": {
"created_at": "2024-04-30T08:51:18.177543Z",
"cred_def_id": "QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic",
"cred_ex_id": "af4bad3f-3fcc-47ab-85e6-24224dcb2779",
"cred_ex_version": "2",
"cred_rev_id": "2",
"record_id": "57bd9c72-fa29-4f65-bd89-4e241471073a",
"rev_reg_id": "QrMaE11MnC6zjKNY1pxbq8:4:QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic:CL_ACCUM:53462552-d716-4b0b-8b5c-914a3574d2c4",
"state": "revoked",
"updated_at": "2024-04-30T12:21:16.686124Z"
}
}
The revocation status endpoint will also be updated to the new state.
GET /v1/issuer/credentials/revocation/record?credential_exchange_id=v2-af4bad3f-3fcc-47ab-85e6-24224dcb2779
{
"created_at": "2024-04-30T08:51:18.177543Z",
"cred_def_id": "QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic",
"cred_ex_id": "af4bad3f-3fcc-47ab-85e6-24224dcb2779",
"cred_ex_version": "2",
"cred_rev_id": "2",
"record_id": "57bd9c72-fa29-4f65-bd89-4e241471073a",
"rev_reg_id": "QrMaE11MnC6zjKNY1pxbq8:4:QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic:CL_ACCUM:53462552-d716-4b0b-8b5c-914a3574d2c4",
"state": "revoked",
"updated_at": "2024-04-30T12:21:16.686124Z"
}
For emphasis: every credential revoked in this manner will trigger a ledger operation, which incurs a cost. If an issuer has multiple credentials to revoke, it is recommended not to auto-publish to the ledger.
Manual Publishing of Revocations (Batching)
By setting "auto_publish_on_ledger"
to false, an issuer can call
revoke on all the credential exchange ids they would like to revoke without
performing multiple ledger operations.
POST /v1/issuer/credentials/revoke
{
"credential_exchange_id": "v2-6dbfbeeb-468f-4017-93f7-09c3602b15d4",
"credential_definition_id": "QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic",
"auto_publish_on_ledger": false
}
The endpoint will respond with:
{
"cred_rev_ids_published": {}
}
However, the "issuer_cred_rev"
event won't fire after every call as it does with "auto_publish_on_ledger": true
,
because the credential's status will only update when the revocation has been published to the ledger.
This is also reflected in the revocation record, as the state remains issued.
GET /v1/issuer/credentials/revocation/record?credential_exchange_id=v2-6dbfbeeb-468f-4017-93f7-09c3602b15d4
{
"created_at": "2024-04-30T12:49:25.210664Z",
"cred_def_id": "QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic",
"cred_ex_id": "6dbfbeeb-468f-4017-93f7-09c3602b15d4",
"cred_ex_version": "2",
"cred_rev_id": "3",
"record_id": "287a40fe-a23e-4675-b21f-5b72835b25be",
"rev_reg_id": "QrMaE11MnC6zjKNY1pxbq8:4:QrMaE11MnC6zjKNY1pxbq8:3:CL:8:Epic:CL_ACCUM:53462552-d716-4b0b-8b5c-914a3574d2c4",
"state": "issued",
"updated_at": "2024-04-30T12:49:25.210664Z"
}
Once revocation is called on all the credential exchange ids that need to be revoked, the revocations can then be published to the ledger.
Revocations that were called with "auto_publish_on_ledger": false"
are pending publication.
An issuer can either publish these revocations or clear the revocation, i.e., not revoke the credential.
Publishing Pending Revocations
The publish revocation endpoint can be used to publish revocations in bulk, or an issuer can be very specific about which revocations they want to publish.
The body sent to the endpoint specifies what needs to be published. This body is a revocation registry to credential map/dictionary.
Each key is a revocation registry ID (rev_reg_id
), and its value is a list
of credential revocation IDs (cred_rev_id
) to be published.
The payload below will publish 6 revocations across two registries.
POST /v1/issuer/credentials/publish-revocations
{
"revocation_registry_credential_map": {
"WWzcvsHULP1Fkf9GUYRZg8:4:WWzcvsHULP1Fkf9GUYRZg8:3:CL:8:Epic:CL_ACCUM:cd2e0473-31f7-4cde-883d-6fceac1ce0d7": [
"1",
"2",
"3"
],
"WWzcvsHULP1Fkf9GUYRZg8:4:WWzcvsHULP1Fkf9GUYRZg8:3:CL:8:Epic:CL_ACCUM:bf1219ca-75bf-4931-911b-1fe2ace39683": [
"1",
"2",
"4"
]
}
}
Providing an empty list for a registry ID instructs the system to publish all pending revocations for that ID.
The payload below will publish all pending revocations for the given registry ID (rev_reg_id
).
POST /v1/issuer/credentials/publish-revocations
{
"revocation_registry_credential_map": {
"WWzcvsHULP1Fkf9GUYRZg8:4:WWzcvsHULP1Fkf9GUYRZg8:3:CL:8:Epic:CL_ACCUM:cd2e0473-31f7-4cde-883d-6fceac1ce0d7": []
}
}
An empty map/dictionary signifies that all pending revocations across all registry IDs (belonging to the issuer) should be published.
POST /v1/issuer/credentials/publish-revocations
{
"revocation_registry_credential_map": {}
}
This endpoint responds with:
{
"cred_rev_ids_published": {
"rev_reg_id_1": [1, 2],
"rev_reg_id_2": [0, 3]
}
}
The issuer_cred_rev
event will also fire for every credential that was revoked after the revocations were published.
Clearing Pending Revocations
The clear revocation endpoint functions in the same way as the publish revocation endpoint. Instead of publishing the revocations, it clears them, i.e., the credential is not revoked and is still considered valid.
The response to the clearing endpoint is also different from the publish endpoint. The clear pending revocation endpoint responds with the still pending revocations.
The payload below will clear the pending revocation on cred_rev_id = 5
.
POST /v1/issuer/credentials/clear-pending-revocations
{
"revocation_registry_credential_map": {
"CJnbcDL4vBkRzDSw5dS1Pa:4:CJnbcDL4vBkRzDSw5dS1Pa:3:CL:8:Epic:CL_ACCUM:55bd2b4c-672b-4749-b8d3-b1b8137d1012": ["5"]
}
}
Response of still pending cred_rev_ids
for the registry:
{
"revocation_registry_credential_map": {
"CJnbcDL4vBkRzDSw5dS1Pa:4:CJnbcDL4vBkRzDSw5dS1Pa:3:CL:8:Epic:CL_ACCUM:55bd2b4c-672b-4749-b8d3-b1b8137d1012": [
"1",
"2",
"3",
"4"
]
}
}
This call will clear all pending revocations for the given registry ID.
POST /v1/issuer/credentials/clear-pending-revocations
{
"revocation_registry_credential_map": {
"CJnbcDL4vBkRzDSw5dS1Pa:4:CJnbcDL4vBkRzDSw5dS1Pa:3:CL:8:Epic:CL_ACCUM:55bd2b4c-672b-4749-b8d3-b1b8137d1012": []
}
}
Response (no more pending revocations):
{
"revocation_registry_credential_map": {}
}
This call will clear all revocations for all registries.
POST /v1/issuer/credentials/clear-pending-revocations
{
"revocation_registry_credential_map": {}
}
Response (no more pending revocations):
{
"revocation_registry_credential_map": {}
}
Getting Pending Revocations per Revocation Registry
An issuer can get the pending revocations per revocation registry.
This is very easy to do; just call the following endpoint with the rev_reg_id
:
GET /v1/issuer/credentials/get-pending-revocations/{revocation_registry_id}
Response:
{
"pending_cred_rev_ids": [0, 1, 2, 3]
}
The response contains the integers of the cred_rev_ids
that are pending revocation for the rev_reg_id
called.